package com.itheima.wisdomnext.config;

import com.itheima.wisdomnext.util.JwtUtil;
import com.itheima.wisdomnext.service.ImpI.UserServiceImpI;
import io.jsonwebtoken.JwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.List;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    private static final String AUTH_HEADER = "Authorization";
    private static final String TOKEN_PREFIX = "Bearer ";
    private static final String JSON_TYPE = "application/json;charset=UTF-8";

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private UserServiceImpI userService;

    private static final List<String> WHITE_LIST = List.of(
            "/api/user/register", "/api/user/login",
            "/api/admin/register", "/api/admin/login",
            "/api/announcements/all",
            "/api/categorie/show", "/api/categorie/posts/",
            "/api/comment/post/", "/api/comment/reply/",
            "/api/reports/reasons",
            "/api/post/checkline/", "/api/post/All", "/api/post/recent",
            "/api/topic/", "/uploaded_images/", "/uploaded_video/",
            //WebSocket的接口
            "/ws",
            //支付宝沙箱接口
            "/alipay"
    );

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {
        String uri = request.getRequestURI();

        // 放行预检请求和白名单
        if ("OPTIONS".equalsIgnoreCase(request.getMethod()) || isWhiteListed(uri)) {
            filterChain.doFilter(request, response);
            return;
        }

        try {
            String token = extractToken(request);
            authenticate(token, request);
            filterChain.doFilter(request, response);
        } catch (JwtException e) {
            sendUnauthorizedResponse(response, e.getMessage());
        }
    }

    private String extractToken(HttpServletRequest request) {
        String header = request.getHeader(AUTH_HEADER);
        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            throw new JwtException("缺少或无效的认证头");
        }
        return header.substring(TOKEN_PREFIX.length());
    }

    private void authenticate(String token, HttpServletRequest request) {
        String username = jwtUtil.getUsernameFromToken(token);
        UserDetails userDetails = userService.loadUserByUsername(username);

        if (!jwtUtil.validateToken(token, userDetails)) {
            throw new JwtException("Token校验失败");
        }

        var authentication = new UsernamePasswordAuthenticationToken(
                userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
        SecurityContextHolder.getContext().setAuthentication(authentication);
    }

    private boolean isWhiteListed(String uri) {
        return WHITE_LIST.stream().anyMatch(uri::startsWith);
    }

    private void sendUnauthorizedResponse(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(JSON_TYPE);
        response.getWriter().write("{\"code\":401,\"msg\":\"认证失败: " + message + "\"}");
    }
}
